package com.alinesno.cloud.gateway.core.dispather.socket;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alinesno.cloud.gateway.core.context.ApplicationContextProvider;
import com.alinesno.cloud.gateway.core.dispather.socket.bean.BusinessServerBean;
import com.alinesno.cloud.gateway.core.dispather.socket.channel.ServerChannelInitializer;
import com.alinesno.cloud.gateway.core.dispather.socket.coder.RequestMessageEncoder;
import com.alinesno.cloud.gateway.core.dispather.socket.coder.ResponseMessageDecoder;

import io.netty.channel.Channel;

/**
 * Socket服务 
 * @author LuoAnDong
 * @since 2019年9月21日 下午7:40:15
 */
@Component
public class NettySocketServer {

	private static final Logger log = LoggerFactory.getLogger(NettySocketServer.class) ; 
	
	@Autowired
	private NettyConfigation nettyConfigation ; 

	// 文件的channel配置
	private static Map<Integer , Channel> channelMap = new HashMap<Integer , Channel>(); 
	private Map<Integer , BusinessServerBean> inetSocketAddressMap ; 

	/**
	 * 启动所有服务 
	 * @throws Exception
	 */
	public void start() throws Exception {
		for(int port : inetSocketAddressMap.keySet()) {
			
			BusinessServerBean addr = inetSocketAddressMap.get(port) ; 
			startChannelByPort(addr) ; 
			
		}
	}

	/**
	 * 通过端口启动服务
	 * @param port
	 * @return
	 * @throws InterruptedException 
	 */
	public Channel startChannelByPort(BusinessServerBean addr) throws InterruptedException {
		
			ServerChannelInitializer serverChannelInitializer = ApplicationContextProvider.getBean(ServerChannelInitializer.class) ;  
			serverChannelInitializer.setListenPort(addr.getServerPort()); // 设置监听端口
			
			// 获取解析器和编码器实现设置_start
			RequestMessageEncoder encoder = new RequestMessageEncoder() ; 
			if(StringUtils.isNotBlank(addr.getEncoder())) {
				encoder = (RequestMessageEncoder) ApplicationContextProvider.getBean("ENCODE_"+addr.getEncoder()) ; 
			}
			serverChannelInitializer.setEncoder(encoder); 
			
			ResponseMessageDecoder decoder = new ResponseMessageDecoder() ; 
			if(StringUtils.isNotBlank(addr.getDecoder())) {
				decoder = (ResponseMessageDecoder) ApplicationContextProvider.getBean("DECODE_"+addr.getDecoder()) ; 
			}
			serverChannelInitializer.setDecoder(decoder); 
			// 获取解析器和编码器实现设置_end 
			
			Channel chanel = nettyConfigation
								 .bootstrap(serverChannelInitializer)
								 .bind(new InetSocketAddress(addr.getServiceIp() , addr.getServerPort()))
								 .sync()
								 .channel() ; 
			
			log.debug("启动 【{}】 netty socket服务:IP:{} , Port:{} " , addr.getBusinessDesc() , addr.getServerPort() , addr.getServerPort());
		
			channelMap.put(addr.getServerPort() , chanel) ; 
			
			return chanel ; 
	}
	
	/**
	 * 停止接口
	 * @throws Exception
	 */
	public void stop() throws Exception {
		log.debug("销毁netty socket服务") ; 
		
		for(int port : channelMap.keySet()) {
			stopByPort(port); 
		}
	}
	
	/**
	 * 通过端口停止
	 * @param port
	 * @throws Exception
	 */
	public void stopByPort(int port) throws Exception {
		Channel serverChannel = channelMap.get(port) ; 
		serverChannel.close();
		serverChannel.parent().close();
	}

	public Map<Integer, BusinessServerBean> getInetSocketAddressMap() {
		return inetSocketAddressMap;
	}

	public void setInetSocketAddressMap(Map<Integer, BusinessServerBean> inetSocketAddressMap) {
		this.inetSocketAddressMap = inetSocketAddressMap;
	}

}